/* JavaLog - package tracker 
 * 
 * Copyright (C) 2009 Allyson Lima, Diego Pedro, Victor Freire
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software 
 * Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this 
 * program. If not, see <http://www.gnu.org/licenses/>.
 */

package br.edu.ufcg.ccc.javalog.model;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import br.edu.ufcg.ccc.javalog.exceptions.FranchiseException;
import br.edu.ufcg.ccc.javalog.exceptions.HeadquartersException;
import br.edu.ufcg.ccc.javalog.exceptions.PackageException;

/**
 * Headquarters.
 * 
 * @author Allyson Lima, Diego Pedro, Victor Freire
 * @version 08/11/09
 */
public class Headquarters extends Franchise {
	/**
	 * Key: the city the franchise is in - Value: the franchise
	 */
	private static final Map<String, Franchise> franchises = new HashMap<String, Franchise>();

	public Headquarters(String name, Address address, boolean hasAirport)
			throws FranchiseException {
		super(name, address, hasAirport);
		addFranchise(this);
	}

	/**
	 * Searches and returns the most profitable franchise.
	 * 
	 * @return most profitable franchise.
	 */
	public Franchise mostProfitableFranchise() {
		// TODO
		return null;
	}

	/**
	 * Returns the franchise that has handled the highest number of packages.
	 * 
	 * @return most active franchise
	 */
	public Franchise mostActiveFranchise() {
		// TODO
		return null;
	}

	/**
	 * Creates a new franchise in the database.
	 * 
	 * @return true if succeeded, false if there is already a franchise in that
	 *         address.
	 */
	public boolean addFranchise(Franchise f) {
		if (franchises.containsKey(f.getAddress().getCity()))
			return false;
		franchises.put(f.getAddress().getCity(), f);
		return true;
	}

	/**
	 * Searches for the desired franchise.
	 * 
	 * @param addr
	 *            franchise location
	 * @return requested franchise
	 */
	public Franchise getFranchise(String city) {
		return franchises.get(city);
	}

	/**
	 * List the franchises that match the partial franchise name and city name
	 * provided. An empty string means any, it matches in all comparisons.
	 * 
	 * @param name
	 *            partial franchise name to compare, if it is an empty string it
	 *            compares true.
	 * @param city
	 *            partial city name to compare, if it is an empty string it
	 *            compares true.
	 * @return the franchises that match the request
	 * @throws IllegalArgumentException
	 *             when one of the arguments is null
	 */
	public Set<Franchise> listFranchises(String name, String city) {
		// These strings can be empty!
		Validator.validateObject(name, new IllegalArgumentException(
				"received null name string"));
		Validator.validateObject(city, new IllegalArgumentException(
				"received null city string"));

		Set<Franchise> listFranchise = new HashSet<Franchise>();
		for (Franchise f : franchises.values())
			if (f.matches(name, city))
				listFranchise.add(f);
		return listFranchise;
	}

	/**
	 * Remove a franchise.
	 * 
	 * @param city
	 *            the city where the franchise is
	 * @return the removed Franchise or null if failed
	 */
	public Franchise removeFranchise(String city) throws HeadquartersException {
		if (this == franchises.get(city))
			throw new HeadquartersException("Não é possível apagar a Matriz.");
		else
			return franchises.remove(city);
	}

	/**
	 * Remove a franchise.
	 * 
	 * @param addr
	 *            the franchise location
	 * @return the removed Franchise or null if failed
	 * @throws HeadquartersException
	 */
	public Franchise removeFranchise(Franchise f) throws HeadquartersException {
		return removeFranchise(f.getAddress().getCity());
	}

	/**
	 * Moves all packages in transit for with franchise
	 * 
	 * @throws PackageException
	 *             Illegal entry for package
	 */
	public void moveAllPackages() throws PackageException {
		for (Franchise f : franchises.values())
			while (f.movePackages())
				;
	}
}
